from tempo import *
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
import logging
import preprocess_2_data_distribution_compute
import base64
import io
import matplotlib.font_manager as fm

# 配置日志级别和基本设置
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    filename='app.log',
                    filemode='a')

__Cannel_TASK_WAIT_HANDLE__ = False

def Channel():
    __Cannel_TASK_WAIT_HANDLE__ = True

def binary_strings_to_integers(binary_strings):
    # 将所有输入的二进制字符串转换为整数的列表
    result = []
    # 如果字符串长度不是8的倍数，在前面补零
    if len(binary_strings) % 8 != 0:
        binary_strings = binary_strings + '0'
    # 按照每8个字符分组
    chunks = [binary_strings[i:i+8] for i in range(0, len(binary_strings), 8)]
    # 将每个8位的二进制字符串转换为整数
    integers = [int(chunk, 2) for chunk in chunks]
    result.extend(integers)
    return result

def binary_df_to_mingmi(df, L):
    # 创建两个列表来保存明文和密文数据
    all_list_ming = []
    all_list_mi = []
    # 遍历每一行的数据
    for _, row in df.iterrows():
        if __Cannel_TASK_WAIT_HANDLE__ == False:
            data = row['data']
            label = row['label']
            # 将二进制字符串转换为整数
            byte_str = binary_strings_to_integers(data)
            if len(byte_str) > L:
                byte_str = byte_str[:L]
            elif len(byte_str) < L:
                byte_str += [0] * (L - len(byte_str))  # 用0填充
            if label == 0:
                all_list_ming.append(byte_str)
            else:
                all_list_mi.append(byte_str)
        else:
            raise "用户已取消当前操作"
    print('数据加载成功')
    logging.info('数据加载成功')
    return np.array(all_list_ming), np.array(all_list_mi)


def data_distri_plot(d, name):
    my_font = fm.FontProperties()
    my_size = 12
    my_font.set_size(my_size)

    fig = plt.figure(figsize=(6, 6), facecolor='none')
    ax = fig.add_subplot(111, projection='3d')
    for i in range(0, d.shape[1]):
        a, b = np.histogram(d[:, i], 256, [0, 256])
        # 计算总的频数
        total_count = a.sum()
        # 将频次转换为百分比
        a_percent = (a / total_count) * 100
        #    ax.bar(b[0:-1],a, zs=i, zdir='y', alpha=1)
        ax.plot3D(b[2:], a_percent[1:], zs=i, zdir='y')
        if d.shape[1] == 21:
            ax.yaxis.set_major_locator(plt.MultipleLocator(3))  # 设置主要刻度
    # 设置刻度标签颜色为白色
    ax.xaxis.set_tick_params(colors='white')
    ax.yaxis.set_tick_params(colors='white')
    ax.zaxis.set_tick_params(colors='white')

    ax.set_yticks(np.arange(0, d.shape[1], 2))
    ax.set_xlabel(u'字节取值(0~255)', fontproperties=my_font, color='white')
    ax.set_ylabel(u'字节偏移量', fontproperties=my_font, color='white')
    ax.set_zlabel('出现频率（%）', fontproperties=my_font, rotation=90, color='white')
    plt.rcParams['axes.unicode_minus'] = False
    plt.savefig(f'{name}.png', dpi=300, bbox_inches='tight', transparent=True)  # 指定分辨率保存
    buf = io.BytesIO()
    plt.savefig(buf, format='png', transparent=True)
    buf.seek(0)
    image_zhanshi = base64.b64encode(buf.getvalue()).decode('utf-8')

    return image_zhanshi

def main(parameters):
    waibu_data_1 = parameters['waibu_data_1']
    jieduan = parameters['jieduan']

    data = pd.read_csv(waibu_data_1)
    data1, data2 = binary_df_to_mingmi(data, jieduan)

    img_zhanshi_ming = data_distri_plot(data1, 'ming_distri')
    img_zhanshi_mi = data_distri_plot(data2, 'mi_distri')

    # plt.show()
    # plt.close('all')

    result_dict = {
        'img_zhanshi_ming': img_zhanshi_ming,     # 界面1，mode=0，图:明数据分布
        'img_zhanshi_mi': img_zhanshi_mi,     # 界面1，mode=0，图:密数据分布
        'form_1': data1,   # 界面1，mode=0，明数据展示表，可以像xls一样上下左右滚动
        'form_2': data2,   # 界面1，mode=0，密数据展示表，可以像xls一样上下左右滚动
    }
    return result_dict

if __name__ == '__main__':
    parameters1 = {
        'waibu_data_1': r'D:\pythonProject\mingmi\dataset\外部数据_分类004.csv',
        'jieduan': 20  # int，数据截断长度，(0:1:40]可输入可上下箭头调节
    }
    result_dict = main(parameters1)